/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_orm.htm
 *
 * Zhiqim ORM is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.orm;

import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.List;

import org.zhiqim.kernel.service.MultiInstance;
import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.annotation.AnNonnull;
import org.zhiqim.kernel.annotation.AnNullable;
import org.zhiqim.kernel.model.maps.MapSO;
import org.zhiqim.kernel.model.maps.MapSS;
import org.zhiqim.kernel.paging.PageResult;
import org.zhiqim.orm.dbo.Batcher;
import org.zhiqim.orm.dbo.Selector;
import org.zhiqim.orm.dbo.Updater;
import org.zhiqim.orm.dbo.defined._Table;

/**
 * 标准类与数据库表映射调用，支持(truncate,exist,insert,replace,update,delete,count,sum,item,list,page)<br><br>
 * truncate,    清除表类对应的表<br>
 * exist,       检查表类对应的表是否存在<br>
 * create       创建表类对应的表
 * insert,      插入表类对应的表一条数据<br>
 * replace,     替换表类对应的表一条数据，根据主键<br>
 * update,      更新表类对应的表一条数据或根据条件更新数据<br>
 * delete,      删除表类对应的表一条数据或根据条件删除数据<br>
 * count,       统计表类对应的表数目<br>
 * sum,         总计表类对应的表数目<br>
 * item,        查询表类对应的表一条数据，根据主键，或根据条件排序取第一条<br>
 * list,        查询表类对应的表列表，或根据条件排序<br>
 * pag,         分页查询表类对应的表列表，指定分页页码和页数目<br>
 *
 * @version v1.0.0 @author zouzhigang 2014-3-21 新建与整理
 * @version v1.2.0 @author zouzhigang 2016-6-27 修改原类名FDBO为ZTable，正式使用表类名称
 */
@AnAlias("ZTable")
public interface ZTable extends MultiInstance
{
    /**
     * 通过表名获取表对象
     * 
     * @param tableName     表名
     * @return              表对象
     */
    public _Table getTableByTableName(String tableName);
    
    /**
     * 更新数据到缓存
     * 
     * @param cls           表类
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public <T> void cache(Class<T> cls) throws ORMException, SQLException;
    
    /**
     * 获取缓存原生数据列表，警告：不允许对列表作增删改操作，以及对每条数据作修改
     * 
     * @param cls           表类
     * @return              缓存原始数据
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    @AnNonnull               //未查到数据为空列表
    public <T> List<T> cacheListRaw(Class<T> cls) throws ORMException, SQLException;
    
    /**
     * 获取缓存原生数据列表，警告：不允许对列表作增删改操作，以及对每条数据作修改
     * 
     * @param cls           表类
     * @param selector      对象查询器
     * @return              返回表对象列表
     * @throws ORMException 映射异常,如果传入的属性不在配置文件中则异常
     * @throws SQLException 数据库异常
     */
    @AnNonnull               //未查到数据为空列表
    public <T> List<T> cacheListRaw(Class<T> cls, Selector selector) throws ORMException, SQLException;
    
    /**
     * 通过主键获取缓存原生一条数据，警告：不允许数据作修改
     * 
     * @param cls           表类
     * @param ids           表主键
     * @return              缓存原始数据
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    @AnNullable              //根据主键没查到数据情况
    public <T> T cacheItemRaw(Class<T> cls, Object... ids) throws ORMException, SQLException;
    
    /**
     * 批量处理插入/更新/删除数据
     * 
     * @param list          批量表
     * @return              响应表
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int[] batch(List<Batcher> list) throws ORMException, SQLException;
    
    /********************************************************************************************/
    //exist 表是否存在
    /********************************************************************************************/
    
    /**
     * 是否存在[表类]对应的[实际表]
     * 
     * @param cls           表类
     * @return              =true表示存在，=false表示不存在
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public boolean exists(Class<?> cls) throws ORMException, SQLException;

    /**
     * 是否存在[表类]对应的[实际表]分表编号，支持表名中替换字段指定为$ID$，如LOG_TRACE$ID$
     * 
     * @param cls           表类
     * @param id            分表编号
     * @return              =true表示存在，=false表示不存在
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public boolean exists(Class<?> cls, String id) throws ORMException, SQLException;
    
    /**
     * 是否存在[表类]对应的[实际表]可替换表，支持表名中有多个替换字段，如LOG_TRACE_$MONTH$_$ID$
     * 
     * @param cls           表类
     * @param replaceMap    可替换字段表
     * @return              =true表示存在，=false表示不存在
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public boolean exists(Class<?> cls, MapSS replaceMap) throws ORMException, SQLException;

    /********************************************************************************************/
    //create 创建表
    /********************************************************************************************/
    
    /**
     * 创建[表类]对应的[实际表]
     * 
     * @param cls         表类
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public void create(Class<?> cls) throws ORMException, SQLException;
    
    /**
     * 创建[表类]对应的[实际表]ID分表
     * 
     * @param cls           表类
     * @param id            分表编号
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public void create(Class<?> cls, String id) throws ORMException, SQLException;
    
    /**
     * 创建[表类]对应的[实际表]可替换表，支持表名中有多个替换字段，如LOG_TRACE_$MONTH$_$ID$
     * 
     * @param cls           表类
     * @param replaceMap    可替换字段表
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public void create(Class<?> cls, MapSS replaceMap) throws ORMException, SQLException;
    
    /********************************************************************************************/
    //drop 删除表
    /********************************************************************************************/
    
    /**
     * 创建[表类]对应的[实际表]
     * 
     * @param cls           表类
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public void drop(Class<?> cls) throws ORMException, SQLException;
    
    /**
     * 创建[表类]对应的[实际表]分表
     * 
     * @param cls           表类
     * @param id            分表编号
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public void drop(Class<?> cls, String id) throws ORMException, SQLException;
    
    /**
     * 创建[表类]对应的[实际表]可替换表，支持表名中有多个替换字段，如LOG_TRACE_$MONTH$_$ID$
     * 
     * @param cls           表类
     * @param replaceMap    可替换字段表
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public void drop(Class<?> cls, MapSS replaceMap) throws ORMException, SQLException;
    
    /********************************************************************************************/
    //truncate 清空表
    /********************************************************************************************/
    
    /**
     * 清空[表类]对应的[实际表]
     * 
     * @param cls           表类
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public void truncate(Class<?> cls) throws ORMException, SQLException;
    
    /**
     * 清空[表类]对应的[实际表]分表，支持表名中替换字段指定为$ID$，如LOG_TRACE$ID$
     * 
     * @param cls         表类
     * @param id            分表编号
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public void truncate(Class<?> cls, String id) throws ORMException, SQLException;
    
    /**
     * 清空[表类]对应的[实际表]，支持表名中有多个替换字段，如LOG_TRACE_$MONTH$_$ID$
     * 
     * @param cls           表类
     * @param replaceMap    替换表
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public void truncate(Class<?> cls, MapSS replaceMap) throws ORMException, SQLException;
    
    /********************************************************************************************/
    //insert 插入数据
    /********************************************************************************************/
    
    /**
     * 增加数据,传入标准[表类]对象
     * 
     * @param data          表对象
     * @return int          表示插入的条数
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int insert(Object data) throws ORMException, SQLException;

    /**
     * 增加数据，支持表或字段中中有多个替换字段，如LOG_TRACE_$MONTH$_$ID$
     * 
     * @param data          表对象
     * @param replaceMap    适配表
     * @return              int 表示插入的条数
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int insert(Object data, MapSS replaceMap) throws ORMException, SQLException;
    
    /**
     * 替换数据,传入标准[表类]对象和更新器（取fieldMap和replaceMap）当存在时指定修改的值
     * 
     * @param data          表对象
     * @param updater       更新器
     * @return              int 表示插入的条数
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int insertOrUpdate(Object data, Updater updater) throws ORMException, SQLException;
    
    /**
     * 批量增加数据
     * 
     * @param dataList      表对象列表
     * @return              int 表示插入的条数
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int[] insertBatch(List<?> dataList) throws ORMException, SQLException;
    
    /**
     * 批量增加数据，支持表或字段中中有多个替换字段，如LOG_TRACE_$MONTH$_$ID$
     * 
     * @param dataList      表对象列表
     * @param replaceMap    适配表
     * @return              int 表示插入的条数
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int[] insertBatch(List<?> dataList, MapSS replaceMap) throws ORMException, SQLException;
    
    /********************************************************************************************/
    //replace 替换数据，MYSQL支持，如果有数据先删除后增加
    /********************************************************************************************/
    
    /**
     * 替换数据,传入标准[表类]对象
     * 
     * @param data          表对象
     * @return              int 表示插入的条数
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int replace(Object data) throws ORMException, SQLException;

    /**
     * 替换数据，支持表或字段中有多个替换字段，如LOG_TRACE_$MONTH$_$ID$
     * 
     * @param data          表对象
     * @param replaceMap    适配表
     * @return              int 表示插入的条数
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int replace(Object data, MapSS replaceMap) throws ORMException, SQLException;

    /**
     * 批量替换数据
     * 
     * @param dataList      表对象列表
     * @return              int 表示插入的条数
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int[] replaceBatch(List<?> dataList) throws ORMException, SQLException;
    
    /**
     * 批量替换数据，支持表或字段中中有多个替换字段，如LOG_TRACE_$MONTH$_$ID$
     * 
     * @param dataList      表对象列表
     * @param replaceMap    适配表
     * @return              int 表示插入的条数
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int[] replaceBatch(List<?> dataList, MapSS replaceMap) throws ORMException, SQLException;
    
    /********************************************************************************************/
    //update 更新数据
    /********************************************************************************************/
    
    /**
     * 更新数据，指定更新器需要更新的字段、条件和可替换表
     * 
     * @param cls           表类
     * @param updater       更新器
     * @return              int 表示更新的条数
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int update(Class<?> cls, Updater updater) throws ORMException, SQLException;
    
    /**
     * 更新数据，指定对象，根据主键进行更新，主键值不更新
     * 
     * @param data          表对象
     * @return              int 表示更新的条数
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int update(Object data) throws ORMException, SQLException;
    
    /**
     * 更新数据，指定对象，根据主键进行更新，主键值不更新，支持可替换表
     * 
     * @param data          表对象
     * @param replaceMap    适配表
     * @return              int 表示更新的条数
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int update(Object data, MapSS replaceMap) throws ORMException, SQLException;
    
    /********************************************************************************************/
    //delete 删除数据
    /********************************************************************************************/
    
    /**
     * 删除数据，多个主键时使用
     * 
     * @param cls           表类
     * @param ids           关键属性为数组，多个主键
     * @return              返回删除数
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int delete(Class<?> cls, Object... ids) throws ORMException, SQLException;
    
    /**
     * 删除数据，多个主键时使用
     * 
     * @param cls           表类
     * @param replaceMap    替换表
     * @param ids           关键属性为数组，多个主键
     * @return              返回删除数
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int delete(Class<?> cls, MapSS replaceMap, Object... ids) throws ORMException, SQLException;
    
    /**
     * 删除数据, 根据条件
     * 
     * @param cls           表类
     * @param selector      对象选择器
     * @return              返回删除数
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int delete(Class<?> cls, Selector selector) throws ORMException, SQLException;
    
    /**
     * 批量删除数据，根据主键删除
     * 
     * @param cls           表名
     * @param idsList       关键属性为数组的列表，多个主键列表
     * @param replaceMap    替换表
     * @return              返回删除结果列表
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int[] deleteBatch(Class<?> cls, List<Object[]> idsList) throws ORMException, SQLException;
    
    /**
     * 批量删除数据，根据主键删除
     * 
     * @param cls           表名
     * @param replaceMap    替换表
     * @param idsList       关键属性为数组的列表，多个主键列表
     * @return              返回删除结果列表
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int[] deleteBatch(Class<?> cls, MapSS replaceMap, List<Object[]> idsList) throws ORMException, SQLException;
    
    /********************************************************************************************/
    //count 查询数目
    /********************************************************************************************/
    
    /**
     * 查询数目，多个主键时使用
     * 
     * @param cls           表类
     * @param ids           关键属性值，支持多个
     * @return              存在的数目
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int count(Class<?> cls, Object... ids) throws ORMException, SQLException;

    /**
     * 查询数目，整表查询
     * 
     * @param cls           表类
     * @return              int 数目值
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int count(Class<?> cls) throws ORMException, SQLException;
    
    /**
     * 查询数目，根据条件、可替换表查询
     * 
     * @param cls           表类
     * @param selector      对象查询器
     * @return              int 数目值
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int count(Class<?> cls, Selector selector) throws ORMException, SQLException;
    
    /**
     * 分组查询数目，根据条件、可替换表和分组字段
     * 
     * @param cls           表类
     * @param selector      对象查询器
     * @return              统计列表
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public List<MapSO> countGroupBy(Class<?> cls, Selector selector) throws ORMException, SQLException;
    
    /********************************************************************************************/
    //sum 计算总和
    /********************************************************************************************/
    
    /**
     * 计算总和
     * 
     * @param cls           表类
     * @param field         表字段
     * @return              计算总和
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public BigDecimal sum(Class<?> cls, String field) throws ORMException, SQLException;
    
    /**
     * 计算总和
     * 
     * @param cls           表类
     * @param selector      对象查询器
     * @param field         表字段
     * @return              计算总和
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public BigDecimal sum(Class<?> cls, Selector selector, String field) throws ORMException, SQLException;
    
    /**
     * 计算多个总和
     * 
     * @param cls           表类
     * @param selector      对象查询器
     * @param fields        多个表字段
     * @return              计算多个总和
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public List<BigDecimal> sum(Class<?> cls, Selector selector, String... fields) throws ORMException, SQLException;
    
    /********************************************************************************************/
    //item 查询一条数据
    /********************************************************************************************/
    
    /**
     * 查询一个表对象，支持多个主键
     * 
     * @param cls           表类
     * @param ids           关键属性值
     * @return              返回表对象
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public <T> T item(Class<T> cls, Object... ids) throws ORMException, SQLException;
    
    /**
     * 查询一个表对象，并指定返回属性,查询第一行
     * 
     * @param cls           表类
     * @return              返回表对象
     * @throws ORMException 映射异常,如果传入的属性不在配置文件中则异常
     * @throws SQLException 数据库异常
     */
    public <T> T item(Class<T> cls) throws ORMException, SQLException;
    
    /**
     * 查询一个表对象，并指定返回属性,查询条件和排序条件
     * 
     * @param cls           表类
     * @param selector      对象查询器
     * @return              返回表对象
     * @throws ORMException 映射异常,如果传入的属性不在配置文件中则异常
     * @throws SQLException 数据库异常
     */
    public <T> T item(Class<T> cls, Selector selector) throws ORMException, SQLException;
    
    /********************************************************************************************/
    //list 查询列表
    /********************************************************************************************/
    
    /**
     * 查询表对象列表，全表查询
     * 
     * @param cls           表类
     * @return              返回表对象列表
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public <T> List<T> list(Class<T> cls) throws ORMException, SQLException;
    
    /**
     * 查询表对象列表，并指定返回属性,查询条件和排序条件
     * 
     * @param cls           表类
     * @param selector      对象查询器
     * @return              返回表对象列表
     * @throws ORMException 映射异常,如果传入的属性不在配置文件中则异常
     * @throws SQLException 数据库异常
     */
    public <T> List<T> list(Class<T> cls, Selector selector) throws ORMException, SQLException;
    
    /**
     * 查询表对象列表，查询指定的位置的数据
     * 
     * @param cls           表类
     * @param pageNo        页码
     * @param pageSize      页数
     * @return              返回表对象列表
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public <T> List<T> list(Class<T> cls, int pageNo, int pageSize) throws ORMException, SQLException;
    
    /**
     * 查询表对象列表，并指定位置的,条件和排序条件
     * 
     * @param cls           表类
     * @param pageNo        页码
     * @param pageSize      页数
     * @param selector      对象查询器
     * @return              返回表对象列表
     * @throws ORMException 映射异常,如果传入的属性不在配置文件中则异常
     * @throws SQLException 数据库异常
     */
    public <T> List<T> list(Class<T> cls, int pageNo, int pageSize, Selector selector) throws ORMException, SQLException;
    
    /********************************************************************************************/
    //page 分页显示
    /********************************************************************************************/
    
    /**
     * 查询表对象分页信息
     * 
     * @param cls           表类
     * @param pageNo        页码
     * @param pageSize      页数
     * @return              分页信息,包括总页数,页码,页数和查询的记录
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public <T> PageResult<T> page(Class<T> cls, int pageNo, int pageSize) throws ORMException, SQLException;

    /**
     * 查询表对象分页信息
     * 
     * @param cls           表类
     * @param pageNo        页码
     * @param pageSize      页数
     * @param selector      对象查询器
     * @return              分页信息,包括总页数,页码,页数和查询的记录
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public <T> PageResult<T> page(Class<T> cls, int pageNo, int pageSize, Selector selector) throws ORMException, SQLException;
    
    /**
     * 查询表对象分页信息
     * 
     * @param cls           表类
     * @param pageNo        页码
     * @param pageSize      页数
     * @param total         指定总数，不作count
     * @return              分页信息,包括总页数,页码,页数和查询的记录
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public <T> PageResult<T> page(Class<T> cls, int pageNo, int pageSize, int total) throws ORMException, SQLException;
    
    /**
     * 查询表对象分页信息
     * 
     * @param cls           表类
     * @param pageNo        页码
     * @param pageSize      页数
     * @param selector      对象查询器
     * @param total         指定总数，不作count
     * @return              分页信息,包括总页数,页码,页数和查询的记录
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public <T> PageResult<T> page(Class<T> cls, int pageNo, int pageSize, int total, Selector selector) throws ORMException, SQLException;
    
}
